﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using PlanningGIS.Engine.Controls;
using ESRI.ArcGIS.Geodatabase;
using PlanningGIS.ArcGIS;
using DevComponents.DotNetBar.SuperGrid;
using PlanningGIS.Win.Controls;
using PlanningGIS.Framework.Rule;
using PlanningGIS.ManageUtility.Modules;
using PlanningGIS.Framework;

namespace PlanningGIS.DataConvert
{
    public partial class FrmDataAppend : Office2007Form
    {

        /// <summary>
        /// 要入库的源数据
        /// </summary>
        private List<IFeatureClass> _SourceDataSets = null;

        /// <summary>
        /// 数据入库操作
        /// </summary>
        private ImpJob _Job = null;

        /// <summary>
        /// 目标数据工作空间
        /// </summary>
        private IWorkspace _WorkspaceTarget = null;

        /// <summary>
        /// 目标数据要素类集合
        /// </summary>
        private List<IFeatureClass> _TargetFeatClses = null;

        /// <summary>
        /// 窗体标题
        /// </summary>
        private string tile = "数据导入";

        /// <summary>
        /// 源数据表列表控件列名
        /// </summary>
        const string _clnSrcName = "clnSrcName";

        /// <summary>
        /// 目标数据表列表控件列名
        /// </summary>
        const string _clnAimName = "clnAimName";

        /// <summary>
        /// 源数据表字段列表控件列名
        /// </summary>
        const string _clnSrcFdName = "clnSrcFdName";

        /// <summary>
        /// 目标数据表字段列表控件列名
        /// </summary>
        const string _clnAimFdName = "clnAimFdName";

        public FrmDataAppend()
        {
            InitializeComponent();
        }
        
        /// <summary>
        /// 窗体图标
        /// </summary>
        public string Tile
        {
            get { return tile; }
            set { tile = value; }
        }


        /// <summary>
        /// 验证参数是否正确
        /// </summary>
        /// <returns></returns>
        private bool ValiadParam()
        {
            _SourceDataSets = ctlDataSetList.Datasets;
            if (_SourceDataSets == null || _SourceDataSets.Count == 0)
            {
                MsgHelper.ShowInfomationAlert("数据源为空！");
                return false;
            }
            if (supertbctlDb.SelectedTab == supertbitmSde && (String.IsNullOrWhiteSpace(txtIP.Text.Trim()) || String.IsNullOrWhiteSpace(txtUser.Text.Trim())
                || String.IsNullOrWhiteSpace(txtPassword.Text.Trim()) || String.IsNullOrWhiteSpace(txtOrcl.Text.Trim())))
            {
                MsgHelper.ShowInfomationAlert("目标库体设置不正确！");
                return false;
            }
            else if (supertbctlDb.SelectedTab == supertbitmLocal && String.IsNullOrWhiteSpace(txtPath.Text.Trim())) 
            {
                MsgHelper.ShowInfomationAlert("目标库体设置不正确！");
                return false;
            }
            return true;
        }

        /// <summary>
        /// 若使用图层入库时需要设置图层匹配关系
        /// </summary>
        /// <returns></returns>
        private List<MatchFieldName> GetMatchFields()
        {
            if (superGrdFields.PrimaryGrid.Rows.Count == 0) return null;
            List<MatchFieldName> ms = new List<MatchFieldName>();
            foreach (GridRow r in superGrdFields.PrimaryGrid.Rows)
            {
                object o = r.Cells[_clnAimName].Value;
                if (o == null || string.IsNullOrWhiteSpace(o.ToString())) continue;
                if (r.Rows.Count == 0) continue;
                GridPanel p = (r.Rows[0] as GridPanel);
                if (p.Rows.Count == 0) continue;
                MatchFieldName m = new MatchFieldName()
                {
                    SourceName = r.Cells[_clnSrcName].Value.ToString(),
                    TargetName = o.ToString()
                };
                m.Fields = new Dictionary<string, string>();
                foreach (GridRow sr in p.Rows)
                {
                    object fdo = sr.Cells[_clnAimFdName].Value;
                    if (fdo == null || string.IsNullOrWhiteSpace(fdo.ToString())) continue;
                    m.Fields.Add(sr.Cells[_clnSrcFdName].Value.ToString(), fdo.ToString());
                }
                ms.Add(m);
            }
            return ms;
        }

        /// <summary>
        /// 匹配的目标图层选择改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void colaimname_SelectedValueChanged1(object sender, EventArgs e)
        {
            GridComboBoxExEditControl ctl = (GridComboBoxExEditControl)sender;
            object o = ctl.SelectedItem;
            if (o == null || string.IsNullOrWhiteSpace(o.ToString())) return;
            if (!PlanningGIS.ArcGIS.GeodatabaseHelper.ExistsFeatureClass(_WorkspaceTarget, o.ToString())) return;
            IFeatureClass aim = PlanningGIS.ArcGIS.GeodatabaseHelper.OpenFeatureClass(_WorkspaceTarget, o.ToString());
            GridRow r = ((IGridCellEditControl)ctl).EditorCell.GridRow;
            if (r.Rows.Count == 0) return;
            ((IGridCellEditControl)ctl).EditorCell.Value = o.ToString();
            GridPanel grdpanel = (GridPanel)r.Rows[0];
            List<String> aimfields = new List<string>();
            for (int i = 0; i < aim.Fields.FieldCount; i++)
            {
                IField fd = aim.Fields.get_Field(i);
                if (!fd.Editable) continue;
                if (fd.Type == esriFieldType.esriFieldTypeOID ||
                    fd.Type == esriFieldType.esriFieldTypeGeometry) continue;
                aimfields.Add(fd.Name);
            }
            UpdateFields(aimfields, grdpanel);
        }

        /// <summary>
        /// 添加图层对应关系
        /// </summary>
        private void AddColumns()
        {
            GridPanel gdpnl = superGrdFields.PrimaryGrid;
            gdpnl.ShowRowGridIndex = true;
            foreach (dynamic cls in _SourceDataSets)
            {
                if (cls is IFeatureClass)
                {
                    string nm = (cls as IDataset).Name;
                    IFeatureClass aim = null;
                    aim = _TargetFeatClses.FirstOrDefault(t => ((IDataset)t).Name.Equals(nm, StringComparison.CurrentCultureIgnoreCase) ||
                        ((IDataset)t).Name.ToLower().Trim().Contains(nm.ToLower()) ||
                        nm.ToLower().Contains(((IDataset)t).Name.ToLower().Trim()));
                    if (aim == null && (cls as IFeatureClass).FeatureType == esriFeatureType.esriFTAnnotation)
                    {
                        aim = _TargetFeatClses.FirstOrDefault(t => t.FeatureType == esriFeatureType.esriFTAnnotation);
                    }
                    string s = "";
                    IFields aimFields = null;
                    List<String> aimfieldNames = new List<string>();
                    if (aim != null)
                        s = ((IDataset)aim).Name;
                    GridRow r = new GridRow(new string[] { nm, s });
                    gdpnl.Rows.Add(r);
                    GridPanel subpnl = new GridPanel();
                    subpnl.ShowRowGridIndex = true;
                    if (aim != null)
                    {
                        aimFields = aim.Fields;
                        for (int i = 0; i < aim.Fields.FieldCount; i++)
                        {
                            IField fd = aim.Fields.get_Field(i);
                            if (!fd.Editable) continue;
                            if (fd.Type == esriFieldType.esriFieldTypeOID ||
                                fd.Type == esriFieldType.esriFieldTypeGeometry) continue;
                            aimfieldNames.Add(fd.Name);
                        }
                    }
                    AddSubColumns(aimfieldNames, subpnl);
                    AddSubRows((cls as IFeatureClass).Fields, aimFields, subpnl);
                    r.Rows.Add(subpnl);
                    subpnl.EnsureVisible(true);
                }
            }
        }

        /// <summary>
        /// 添加图层字段对应关系
        /// </summary>
        /// <param name="aimFields">目标数据字段</param>
        /// <param name="grdpanel">数据字段容器</param>
        private void AddSubColumns(dynamic aimFields, GridPanel grdpanel)
        {
            GridColumn srcFd = new GridColumn();
            srcFd.EditorType = typeof(GridTextBoxXEditControl);
            srcFd.HeaderText = "源字段名称";
            srcFd.Name = _clnSrcFdName;
            srcFd.Width = 100;
            grdpanel.Columns.Add(srcFd);

            srcFd = new GridColumn();
            srcFd.EditorType = typeof(GridComboBoxExEditControl);
            srcFd.HeaderText = "目标字段名称";
            srcFd.Name = _clnAimFdName;
            srcFd.Width = 100;
            grdpanel.Columns.Add(srcFd);
            GridComboBoxExEditControl ctrl = grdpanel.Columns[_clnAimFdName].EditControl as GridComboBoxExEditControl;
            ctrl.ValueMember = "TargetFieldName";
            ctrl.DisplayMember = "TargetFieldName";
            ctrl.DataSource = aimFields;
        }


        /// <summary>
        /// 添加图层字段项
        /// </summary>
        /// <param name="srcFields">源数据表中的字段信息</param>
        /// <param name="aimFields">目标数据字段(建库规则)</param>
        /// <param name="grdpanel">数据字段容器</param>
        private void AddSubRows(IFields srcFields, List<AttrField> aimFields, GridPanel grdpanel)
        {
            int cnt = srcFields.FieldCount;
            for (int i = 0; i < cnt; i++)
            {
                IField fd = srcFields.get_Field(i);
                if (!fd.Editable) continue;
                if (fd.Type == esriFieldType.esriFieldTypeOID ||
                    fd.Type == esriFieldType.esriFieldTypeGeometry) continue;
                string aim = "";
                if (aimFields != null && aimFields.Count > 0)
                {
                    AttrField aimfd = aimFields.FirstOrDefault(t =>
                        fd.Name.Equals(t.TargetFieldName, StringComparison.CurrentCultureIgnoreCase) ||
                        fd.Name.Equals(t.SourceFieldName, StringComparison.CurrentCultureIgnoreCase));
                    if (aimfd != null && !string.IsNullOrWhiteSpace(aimfd.TargetFieldName)) aim = aimfd.TargetFieldName;
                }
                grdpanel.Rows.Add(new GridRow(new string[] { fd.Name, aim }));
            }
        }

        /// <summary>
        /// 添加图层字段项
        /// </summary>
        /// <param name="srcFields">源数据表中的字段信息</param>
        /// <param name="aimFields">目标数据表中的字段信息</param>
        /// <param name="grdpanel">数据字段容器</param>
        private void AddSubRows(IFields srcFields, IFields aimFields, GridPanel grdpanel)
        {
            int cnt = srcFields.FieldCount;
            for (int i = 0; i < cnt; i++)
            {
                IField fd = srcFields.get_Field(i);
                if (!fd.Editable) continue;
                if (fd.Type == esriFieldType.esriFieldTypeOID ||
                    fd.Type == esriFieldType.esriFieldTypeGeometry) continue;
                if (aimFields != null && aimFields.FindField(fd.Name) != -1)
                {
                    grdpanel.Rows.Add(new GridRow(new string[] { fd.Name, fd.Name }));
                }
                else
                {
                    grdpanel.Rows.Add(new GridRow(new string[] { fd.Name, "" }));
                }
            }
        }

        /// <summary>
        /// 匹配的图层选择改变后更新数据字段的数据源
        /// </summary>
        /// <param name="aimFields">数据字段源</param>
        /// <param name="grdpanel">要更新的列表容器</param>
        private void UpdateFields(List<AttrField> aimFields, GridPanel grdpanel)
        {
            if (grdpanel == null || grdpanel.Rows.Count == 0) return;
            GridComboBoxExEditControl ctrl = grdpanel.Columns[_clnAimFdName].EditControl as GridComboBoxExEditControl;
            ctrl.ValueMember = "TargetFieldName";
            ctrl.DisplayMember = "TargetFieldName";
            ctrl.DataSource = aimFields;
            if (aimFields == null || aimFields.Count == 0) return;
            foreach (GridRow r in grdpanel.Rows)
            {
                string nm = r.Cells[_clnSrcFdName].Value.ToString();
                AttrField aimfd = aimFields.FirstOrDefault(t =>
                        nm.Equals(t.TargetFieldName, StringComparison.CurrentCultureIgnoreCase) ||
                        nm.Equals(t.SourceFieldName, StringComparison.CurrentCultureIgnoreCase));
                string am = "";
                if (aimfd != null && !string.IsNullOrWhiteSpace(aimfd.TargetFieldName)) am = aimfd.TargetFieldName;
                r.Cells[_clnAimFdName].Value = am;
            }
        }

        /// <summary>
        /// 匹配的图层选择改变后更新数据字段的数据源
        /// </summary>
        /// <param name="aimFields">数据字段源</param>
        /// <param name="grdpanel">要更新的列表容器</param>
        private void UpdateFields(List<String> aimFields, GridPanel grdpanel)
        {
            if (grdpanel == null || grdpanel.Rows.Count == 0) return;
            GridComboBoxExEditControl ctrl = grdpanel.Columns[_clnAimFdName].EditControl as GridComboBoxExEditControl;
            //ctrl.ValueMember = "TargetFieldName";
            //ctrl.DisplayMember = "TargetFieldName";
            ctrl.DataSource = aimFields;
            if (aimFields == null || aimFields.Count == 0) return;
            foreach (GridRow r in grdpanel.Rows)
            {
                string nm = r.Cells[_clnSrcFdName].Value.ToString();
                String aimfd = aimFields.FirstOrDefault(t =>
                        nm.Equals(t, StringComparison.CurrentCultureIgnoreCase) ||
                        nm.Equals(t, StringComparison.CurrentCultureIgnoreCase));
                string am = "";
                if (aimfd != null && !string.IsNullOrWhiteSpace(aimfd)) am = aimfd;
                r.Cells[_clnAimFdName].Value = am;
            }
        }

        private void btnImp_Click(object sender, EventArgs e)
        {
            if (!ValiadParam()) return;
            List<MatchFieldName> ms = null;
            ms = GetMatchFields();
            if (ms == null || ms.Count == 0)
            {
                MsgHelper.ShowErrorMsgbox(this.ParentForm, "未进行图层字段匹配。");
                return;
            }
            _Job = new ImpJob()
            {
                FeatureClassSource = _SourceDataSets,
                MatchNames = ms,
                ProgressAll = new Progressor() { ProgressBar = pgrbarAll },
                ProgressSub = new Progressor() { ProgressBar = pgrbarSub }
            };
            try
            {
                if (_WorkspaceTarget != null)
                    _Job.WorkspaceTarget = _WorkspaceTarget;
                if (_Job.WorkspaceTarget == null)
                {
                    MsgHelper.ShowErrorMsgbox(this.ParentForm, "目标工作空间创建或打开失败，请修改建库方案。");
                    return;
                }
                _Job.useAppendGP = chkUseGP.Checked;
                bool suc;
                suc = _Job.ImportData();
                Log log = new Log()
                {
                    USER_ID = FrameworkHelper.CurrentUser.ID,
                    USER_NAME = FrameworkHelper.CurrentUser.Name,
                    OP_TYPE = PlanningGIS.ManageUtility.Modules.zjgisLogType.AccessData,
                    NOTES = "申请导入数据",
                    OP_STATUS = zjgisLogStatus.Fail,
                };

                if (suc)
                {
                    log.NOTES = "导入数据成功。";
                    log.OP_STATUS = zjgisLogStatus.Success;
                    MsgHelper.ShowInfomationMsgbox("导入数据成功。\n");
                }
                else
                {
                    MsgHelper.ShowInfomationMsgbox("部分数据未入库成功，请查看日志信息。\n");
                }
                Log.WriteLog(log);
            }
            catch (Exception ex)
            {
                MsgHelper.ShowErrorMsgbox(this.ParentForm, "目标工作空间创建或打开失败，请修改建库方案。" + ex.Message);
                return;
            }
            finally
            {
                _Job.ProgressSub.Stop();
                _Job.ProgressAll.Stop();
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (MsgHelper.ShowYesOrNoQueryMsgBox("正在进行入库，是否确定终止入库？") == DialogResult.Yes)
            {
                if (_Job != null) _Job.Stop();
                btnImp.Enabled = true;
            }
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            OpenDataDialog dlg = new OpenDataDialog();
            dlg.MultiSelect = false;
            if (dlg.ShowDialog(this) != DialogResult.OK) return;
            if (dlg.SelectWorkspace == null) return;
            _WorkspaceTarget = dlg.SelectWorkspace;
            this.Cursor = Cursors.WaitCursor;
            try
            {
                if (dlg.SelectWorkspace.WorkspaceFactory.WorkspaceType == ESRI.ArcGIS.Geodatabase.esriWorkspaceType.esriRemoteDatabaseWorkspace)
                {
                    Dictionary<string, dynamic> properties = dlg.SelectWorkspace.GetProperties();
                    txtIP.Value = properties["Server".ToUpper()];
                    txtUser.Text = properties["User".ToUpper()];
                    //txtPassword.Text = dlg.SelectWorkspace.GetPropertyValue("Password");
                    txtOrcl.Text = properties["Instance".ToUpper()];
                    if (txtOrcl.Text.Contains("/")) txtOrcl.Text = txtOrcl.Text.Split('/')[1];
                    supertbctlDb.SelectedTab = supertbitmSde;
                }
                else
                {
                    txtPath.Text = dlg.SelectWorkspace.GetPropertyValue("Database");
                    supertbctlDb.SelectedTab = supertbitmLocal;
                }
            }
            catch (Exception ex)
            {
                MsgHelper.ShowErrorMsgbox(ex.Message);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void itmExpand_Click(object sender, EventArgs e)
        {
            superGrdFields.PrimaryGrid.ExpandAll();
        }

        private void itmCollapse_Click(object sender, EventArgs e)
        {
            superGrdFields.PrimaryGrid.CollapseAll();
        }

        private void btnMatch_Click(object sender, EventArgs e)
        {
            try
            {
                if (!ValiadParam()) return;
                supertbctlData.SelectedTab = tbitmFields;
                superGrdFields.PrimaryGrid.AllowRowDelete = true;
                for (int i = superGrdFields.PrimaryGrid.Rows.Count - 1; i >= 0; i--)
                {
                    superGrdFields.PrimaryGrid.Rows.Remove(superGrdFields.PrimaryGrid.Rows[i]);
                }
                GridComboBoxExEditControl colaimname = superGrdFields.PrimaryGrid.Columns[_clnAimName].EditControl as GridComboBoxExEditControl;
                List<String> fclnames = new List<string>();
                if (supertbctlDb.SelectedTab == supertbitmSde)
                {
                    try
                    {
                        _WorkspaceTarget = PlanningGIS.ArcGIS.WorkspaceHelper.OpenSDEWorkspace(txtIP.Text.Trim(), txtUser.Text.Trim(), txtPassword.Text.Trim(), txtOrcl.Text.Trim());
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
                else if (supertbctlDb.SelectedTab == supertbitmLocal)
                {
                    _WorkspaceTarget = PlanningGIS.ArcGIS.WorkspaceHelper.CreateOrOpenWorksapce(txtPath.Text.Trim());
                }
                if (_WorkspaceTarget == null)
                {
                    MsgHelper.ShowInfomationMsgbox("打开目标工作空间失败！");
                    return;
                } 
                _TargetFeatClses = GeodatabaseHelper.GetAllFeatureClass((IDataset)_WorkspaceTarget);
                foreach (IFeatureClass featcls in _TargetFeatClses)
                {
                    fclnames.Add(((IDataset)featcls).Name);
                }
                colaimname.DataSource = fclnames;
                AddColumns();
                colaimname.SelectedValueChanged += colaimname_SelectedValueChanged1;
            }
            catch (Exception ex)
            {
                MsgHelper.ShowErrorMsgbox(ex.Message);
            }
        }

        private void FrmDataAppend_Load(object sender, EventArgs e)
        {
            this.Text = Tile;
        }
    }
}
